home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / BUSINESS / XLMATH22.ZIP / SOURCE.ZIP / XLUTIL.C < prev    next >
C/C++ Source or Header  |  1993-09-10  |  27KB  |  1,045 lines

  1. /*******************************************************************
  2.  
  3.   XLUTIL.C
  4.   ==========
  5.  
  6.  Author & Copyright:    
  7.              Roy Kari
  8.              Dept. of Chemistry
  9.             Laurentian University
  10.             Sudbury, Ont.
  11.             Canada        P3E 2C6
  12.             (705) 675-1151
  13.             Internet: "ROY@NICKEL.LAURENTIAN.CA"
  14.  
  15.   This module contains all of the memory management routines for
  16.   Standalone DLL's. Optionally, the memory management is done with the aid
  17.   of the SMARTHEAP memory manager (c) Applegate Software (206)868-8512.
  18.  
  19.   This module also contains pascal string routines and Excel reference
  20.   manipulation rotuines.
  21.   ***************************************************************** */
  22.  
  23. /* --------------------------< Include files >--------------------- */
  24. #define WIN31
  25. #define _MSC_VER 800
  26.  
  27. #include <windows.h>
  28. #include <xlcall.h>
  29.  
  30. #include <stdlib.h>
  31.  
  32. #include <framewrk.h>
  33.  
  34. /*----------------------------------------------------------------------*\
  35.     You can use both XLAUTO and XLUTIL as general purpose modules
  36.     to be included in all of your XLL's. A few modifications are required
  37.     but these are easily handles by logical conditionals such as those
  38.     shown below.
  39. \*----------------------------------------------------------------------*/
  40. #ifdef _XLMATH
  41. #include "xlmath.h"
  42. #endif
  43. #ifdef _XLMARK
  44. #include "xlmark.h"
  45. #endif
  46. #ifdef _XLQC
  47. #include "xlqc.h"
  48. #endif
  49.  
  50.  
  51. #include "xlutil.h"
  52.  
  53.  
  54. /*----------------------------------------------------------------------*\
  55.  
  56.                         Memory Utilities
  57.  
  58.     When I began this project, "real" mode windows was still a reality.
  59.     This meant that memory use was a "real" problem. The only way to
  60.     get by the problem was to use a memory allocator such as SMARTHEAP.
  61.     Today, with Windows 3.1 and finally Microsoft C/C++ 7, one can
  62.     go back to the "old fashioned way" of allocating memory - using 
  63.     the large model compiler and malloc() and free(). SMARTHEAP still 
  64.     provides memory debugging techniques superior to standard C but not 
  65.     superior to C++.
  66.  
  67.     My problem is that I wrote this mess with "real" mode in mind and
  68.     compiled it with casts to near and far pointers. I can easily
  69.     change to use old fashioned memory allocations but I cannot easily
  70.     change to the large model. Hence, what follows is a hybrid. In your
  71.     own usage, I suggest thast you forget about near and far data pointers 
  72.     and let the comiler sort it out.
  73.  
  74. \*----------------------------------------------------------------------*/
  75.  
  76.  
  77. /********************************************************************
  78.  GetMem()
  79.  =============
  80.  This function allocates memory for temporary storage
  81.  ********************************************************************/
  82. LPVOID PASCAL GetMem(WORD wBytes)
  83. {
  84.     LPVOID lpPtr;
  85.      
  86.     if (wBytes > 0)
  87.     {
  88.         lpPtr = (LPVOID)MemAllocPtr(gScratchPool, wBytes, TRUE);
  89.  
  90.         if (lpPtr == NULL)
  91.             ErrorHandler(XLU_NO_MEMORY);
  92.     }
  93.     else
  94.     {
  95.         lpPtr = NULL;
  96.         ErrorHandler(XLU_MEMORY_ERROR);
  97.     }
  98.  
  99.     return (lpPtr);
  100.  
  101. }
  102. /********************************************************************
  103.  FreeMem()
  104.  =============
  105.  This function de-allocates memory previously allocated in GetMem()
  106.  ********************************************************************/
  107. void PASCAL FreeMem(LPVOID lpPtr)
  108. {
  109.     if ((MemFreePtr((LPVOID)lpPtr) == FALSE))
  110.         ErrorHandler(XLU_MEMORY_ERROR);
  111.  
  112.     lpPtr = NULL;
  113.  
  114. }
  115.  
  116. /* -------------------< MALLOC SUBSTITUTE >--------------------- */
  117.  
  118. #ifndef _USE_SMARTHEAP
  119.  
  120. /*
  121. **     Basically, the routines below are dummy routines with the        **
  122. **     exception of the memory allocation routines which simply        **
  123. **     allocate memory in the far heap. If you use standard C            **
  124. **    then you can change the calls to the Microsoft far                **
  125. **    heap allocators _fmalloc() to the standard malloc() etc. I         **
  126. **    didn't because I wanted to retain the ability to use the medium **
  127. **    model with far data pointers.                                    **
  128. */
  129.  
  130. LPVOID PASCAL MemAllocPtr(MEM_POOL pool, WORD wSize,
  131.     BOOL bZeroInit)
  132. {
  133.  
  134.     if (bZeroInit)
  135.         return (LPVOID)_fcalloc((size_t) wSize, sizeof(char));
  136.     else
  137.         return (LPVOID)_fmalloc((size_t)wSize);
  138. }
  139.  
  140. LPVOID PASCAL  MemReAllocPtr(LPVOID lpMem, WORD wSize,
  141.     BOOL bZeroInit)
  142. {
  143.     size_t sizeOld, sizeNew;
  144.     LPVOID lpNew;
  145.  
  146.     if (bZeroInit)
  147.     {
  148.         sizeOld = _fmsize(lpMem);
  149.         lpNew = (LPVOID)_frealloc(lpMem, (size_t)wSize);
  150.         sizeNew = _fmsize(lpNew);
  151.         if ( sizeNew > sizeOld )
  152.         {
  153.             _fmemset((LPVOID)((LPSTR)lpNew+sizeOld), 0, 
  154.                         (size_t)(sizeNew-sizeOld) );
  155.             return lpNew;
  156.         }
  157.     }
  158.     else
  159.         return (LPVOID)_frealloc(lpMem, (size_t)wSize);
  160. }
  161.  
  162. BOOL PASCAL  MemFreePtr(LPVOID lpPtr)
  163. {
  164.     _ffree(lpPtr);
  165.     return TRUE;
  166. }
  167.  
  168. //
  169. //    The following are SMARTHEAP specific routines which here
  170. //    are duplicated as dummy routines.
  171. //
  172. MEM_POOL PASCAL MemPoolInit(BOOL bShared)
  173. {
  174.     return ((MEM_POOL)NULL);
  175. }
  176. BOOL PASCAL MemPoolFree(MEM_POOL pool)
  177. {
  178.     _fheapmin();
  179.     return TRUE;
  180. }
  181. DWORD PASCAL MemPoolCount(MEM_POOL pool)
  182. {
  183.     return (DWORD)0;
  184. }
  185. BOOL PASCAL MemCheckPtr(MEM_POOL pool, LPVOID lpPtr)
  186. {
  187.     // Can't do much here except check to see that the ptr is
  188.     // a ptr to a valid XLOPER of type multi
  189.  
  190.     return TRUE;    // do nothing
  191. }
  192. BOOL PASCAL MemSetSafetyLevel(int Dum1, BOOL bFlag)
  193. {
  194.     return bFlag;
  195. }
  196. #endif    // USE_SMARTHEAP
  197.  
  198. /*----------------------------------------------------------------------*\
  199.  
  200.                             Array Utilities
  201.                             
  202.     All data is passed back to Excel in an XLOPER of type
  203.     xltypeMulti. When using custom functions, this data memory
  204.     is released when Excel calls back xlAutoFree(). When using
  205.     dialog boxes, the memory is released in the dialog box routine.
  206.     It is more convenient to define a xlMulti data structure
  207.     whose memory can be deallocated with a single pointer. The
  208.     function InitMulti() allocates and initializes this xlMulti
  209.     array.
  210.  
  211. \*----------------------------------------------------------------------*/
  212.  
  213. /********************************************************************
  214.  InitMulti()
  215.  =============
  216.  This function allocates the XL MULTI array in global memory &
  217.  inits the array.
  218.  ********************************************************************/
  219. LPMULTI PASCAL InitMulti(WORD wRows, WORD wCols, WORD xlType)
  220. {
  221.     WORD wSizeData = sizeof(XLOPER)*wRows*wCols;
  222.     WORD i;
  223.     LPMULTI lpMulti = NULL;
  224.  
  225.     // the array is allocated in one shot which means
  226.     // that it can be freed with one pointer. There is no
  227.     // need to free the array memory separately
  228.     lpMulti = (LPMULTI)MemAllocPtr(gReturnPool,
  229.                         sizeof(XLOPER)*(wRows*wCols+1), FALSE);
  230.     if (lpMulti)
  231.     {
  232.             // init Multi to call back to xlAutoFree()
  233.             lpMulti->Info.xltype = (xltypeMulti | xlbitDLLFree);
  234.             // set the array pointer
  235.             lpMulti->Info.val.array.lparray = (LPXLOPER)&lpMulti->Data[0];
  236.             // set the rows
  237.             lpMulti->Info.val.array.rows  = wRows;
  238.             // set the columns
  239.             lpMulti->Info.val.array.columns = wCols;
  240.             for (i = 0; i < wRows*wCols; i++)
  241.             {
  242.                 // each XLOPER is initialized to type xlType and zeroed
  243.                 // note that the memory will be freed with lpMulti.
  244.                 lpMulti->Data[i].xltype = xlType;
  245.                 lpMulti->Data[i].val.num = 0.0;
  246.             }
  247.     }
  248.     else
  249.     {
  250.         ErrorHandler(XLU_NO_MEMORY);
  251.         return NULL;
  252.     }
  253.     return (lpMulti);
  254. }
  255. //
  256. //    InitNum() - Init an XLOPER of type Num
  257. //
  258. LPXLOPER PASCAL InitNum(VOID)
  259. {
  260.     LPXLOPER lpxlNum = (LPXLOPER)MemAllocPtr(gReturnPool,
  261.                                     sizeof(XLOPER), TRUE);
  262.     if (lpxlNum)
  263.     {
  264.         lpxlNum->xltype = xltypeNum | xlbitDLLFree;
  265.         lpxlNum->val.num = 0;
  266.     }
  267.     else
  268.     {
  269.         ErrorHandler(XLU_NO_MEMORY);
  270.         return NULL;
  271.     }
  272.     return (lpxlNum);
  273. }
  274. LPXLOPER StripxlbitDLLFree(LPXLOPER lpX)
  275. {
  276.     lpX->xltype = lpX->xltype ^ xlbitDLLFree;
  277.     return (lpX);
  278. }
  279.  
  280.  
  281. /********************************************************************
  282.  InitPointers()
  283.  =============
  284.  This function allocates memory and calculates the pointers for a 2-D
  285.  array. 
  286.  ********************************************************************/
  287. LPLPREAL PASCAL InitPointers(LPREAL lpData,
  288.             WORD wRows, WORD wCols)
  289. {
  290.     WORD id;
  291.     LPLPREAL lplpPtrs;
  292.     WORD wBytes = sizeof(LPREAL)*wRows;
  293.  
  294.     if ((lplpPtrs= (LPLPREAL)GetMem(wBytes))  == N